package com.sh.d1.gatewayserver;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Properties;

/**
 * 游戏服务器发现
 */
public final class GameServerFinder {

    static private final Logger LOGGER = LoggerFactory.getLogger(GameServerFinder.class);

    static private final String NS_SERVER_NAME = "com.sh.d1.gameserver";
    static public final String JOB_TYEP_LOGIN = "LOGIN";
    static public final String JOB_TYEP_GAME = "GAME";
    /**
     * 游戏服务器类型数组
     */
    static private final String[] JOB_TYEP_ARRAY = {JOB_TYEP_LOGIN, JOB_TYEP_GAME};

    static private NamingService _ns = null;

    private GameServerFinder() {
    }

    /**
     * 发现游戏服务器
     */
    static public void startFindGameServer(String serverAddrOfNacos) {
        if (serverAddrOfNacos == null || serverAddrOfNacos.isEmpty()) {
            return;
        }

        Properties prop = new Properties();
        prop.put("serverAddr", serverAddrOfNacos);
        try {
            _ns = NamingFactory.createNamingService(prop);


            for (String jobType : JOB_TYEP_ARRAY) {

                _ns.subscribe(NS_SERVER_NAME,
                        jobType,

                        (oEvent) -> {
                            if (!(oEvent instanceof NamingEvent)) {
                                return;
                            }
                            //获取游戏服务实例表
                            List<Instance> instanceList = ((NamingEvent) oEvent).getInstances();

                            if (null == instanceList ||
                                    instanceList.isEmpty()) {
                                return;
                            }
                            for (Instance gameServerInstance : instanceList) {
                                connectTo(gameServerInstance);
                            }

                        });
            }

        } catch (NacosException ex) {
            LOGGER.error(ex.getMessage(), ex);
        }
    }

    /**
     * 连接到游戏服务器实例
     *
     * @param gameServerInstance 游戏服务器实例
     */
    static private void connectTo(Instance gameServerInstance) {
        if (null == gameServerInstance) {
            return;
        }
        final String serverId = gameServerInstance.getInstanceId();

        if (null == serverId || serverId.isEmpty()) {
            return;
        }
        if (null != NettyClientGroup.getByServerId(serverId)) {
            return;
        }
        NettyClient newClient = new NettyClient(serverId);
        newClient.connect(
                gameServerInstance.getIp(),
                gameServerInstance.getPort());

        NettyClientGroup.add(
                serverId, newClient); //从nacos获取serverId
        newClient.putCloseCallBack((closeFuture) -> {
            LOGGER.warn(
                    "游戏服务器已经关闭, serverId={}"
                    , serverId
            );

            NettyClientGroup.removeByServerId(serverId);
            return null;
        });
    }

    /**
     * 选择一个可用的游戏服务器
     * @param jobType
     * @return
     */
    static public NettyClient selectOnGameServer(String jobType) {
        if (null == jobType ||
                jobType.isEmpty() ||
                null == _ns) {
            return null;
        }
        try {
           List<Instance> gameServerInstancelist = _ns.selectInstances(
                    NS_SERVER_NAME,
                    jobType,
                    true);  //groupname

            if (null == gameServerInstancelist ||
                    gameServerInstancelist.isEmpty()) {
                return null;
            }

          Instance gameServerInstance  =gameServerInstancelist.stream()
                    .max((x,y)->{return  (int) (x.getWeight()-y.getWeight());})
                    .orElse(null);


            return  NettyClientGroup.getByServerId(gameServerInstance.getInstanceId());

        } catch (NacosException ex) {
            LOGGER.error(ex.getMessage(), ex);
        }
        return null;
    }
}
